package com.rbac.web.util;

import com.rbac.web.db.UserDAO;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.apache.ibatis.annotations.Select;

/**
 * @author gengaoliu
 */
public class MyMybatis {

  public static void main(String[] args) {
    UserDAO userMapper = (UserDAO) Proxy.newProxyInstance(MyMybatis.class.getClassLoader(),
        new Class[]{UserDAO.class},
        new InvocationHandler() {
          @Override
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 通过参数来完成替换功能，因此需要先去解析参数
            Map<String, Object> stringObjectMap = parseArgs(method, args);
            // 获取方法上的注解
            Select select = method.getAnnotation(Select.class);
            if (select != null) {
              // 核心逻辑处理
              String[] value = select.value();
              String sql = value[0];
              sql = parseSql(sql,stringObjectMap);
              System.out.println(sql);
            }
            // 数据库操作
            // 结果集的映射处理
            return null;
          }
        });
    userMapper.selectAllById(1);
  }

  public static Map<String, Object> parseArgs(Method method, Object[] args) {
    Map<String, Object> map = new HashMap<>();
    // 获取方法的参数
    Parameter[] parameters = method.getParameters();
    Arrays.asList(parameters).forEach(parameter -> {
      String name = parameter.getName();
      map.put("id", args[0]);
    });
    return map;
  }

  public static String parseSql(String sql, Map<String, Object> map) {
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < sql.length(); i++) {
      char c = sql.charAt(i);
      if (c == '#') {
        int index = i + 1;
        char nextChar = sql.charAt(index);
        if (nextChar != '{') {
          throw new IllegalArgumentException("sql语句有错，不是以{开头");
        }
        StringBuilder argsBuilder = new StringBuilder();
        i = parseSqlArgs(argsBuilder, sql, index);
        String argName = argsBuilder.toString();
        Object value = map.get(argName);
        builder.append(value.toString());
        continue;
      }
      builder.append(c);
    }
    return builder.toString();
  }

  public static int parseSqlArgs(StringBuilder argsBuilder, String sql, int index) {
    index++;
    for(;index<sql.length();index++) {
      char c = sql.charAt(index);
      if (c != '}'){
        argsBuilder.append(c);
        continue;
      }
      if (c == '}'){
        return index;
      }
    }
    throw new IllegalArgumentException("sql语句错误，没有以}结尾");
  }
}
